﻿using System;
using System.Collections.Generic;
using System.Text;
using Evaluant.Uss.Commands;
using System.ComponentModel;
using Evaluant.Uss.Collections;

namespace Evaluant.Uss.Common
{
    public class CommandEventRaiser : ICommandProcessor
    {
        private CancelEntityEventArgs cancelEventArgs;
        private HashedList processedEntityIds = new HashedList();

        #region Events

        public event Evaluant.Uss.ObjectContext.EussCancelEventHandler Insert;
        public event Evaluant.Uss.ObjectContext.EussCancelEventHandler Update;
        public event Evaluant.Uss.ObjectContext.EussCancelEventHandler Delete;
        public event Evaluant.Uss.ObjectContext.EussCancelReferenceEventHandler CreateRelationship;
        public event Evaluant.Uss.ObjectContext.EussCancelReferenceEventHandler RemoveRelationship;

        private void RaiseInsert(string entityId)
        {
            if (Insert != null)
                Insert(entityId, cancelEventArgs);
        }
        private void RaiseUpdate(string entityId)
        {
            if (Update != null)
                Update(entityId, cancelEventArgs);
        }
        private void RaiseDelete(string entityId)
        {
            if (Delete != null)
                Delete(entityId, cancelEventArgs);
        }
        private void RaiseCreateRelationship(string[] ReferenceId)
        {
            ReferenceCancelEventArgs rcea = new ReferenceCancelEventArgs();
            rcea.Cancel = cancelEventArgs.Cancel;
            if (CreateRelationship != null)
                CreateRelationship(ReferenceId, rcea);
            cancelEventArgs = rcea;
        }
        private void RaiseRemoveRelationship(string[] ReferenceId)
        {
            ReferenceCancelEventArgs rcea = new ReferenceCancelEventArgs();
            rcea.Cancel = cancelEventArgs.Cancel;
            if (RemoveRelationship != null)
                RemoveRelationship(ReferenceId, rcea);
            cancelEventArgs = rcea;
        }

        #endregion

        #region ICommandProcessor Membres

        public string NewId
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public void Process(Command command)
        {
        }

        public void Process(CreateEntityCommand command)
        {
            RaiseInsert(command.ParentId);
        }

        public void Process(CompoundCreateCommand command)
        {
            foreach (Command c in command.InnerCommands)
                c.Accept(this);
        }

        public void Process(CompoundUpdateCommand command)
        {
            foreach (Command c in command.InnerCommands)
                c.Accept(this);
        }

        public void Process(DeleteEntityCommand command)
        {
            RaiseDelete(command.ParentId);
        }

        public void Process(CreateAttributeCommand command)
        {
            if (processedEntityIds.Contains(command.ParentId))
                return;
            RaiseInsert(command.ParentId);
            processedEntityIds.Add(command.ParentId);
        }

        public void Process(UpdateAttributeCommand command)
        {
            if (processedEntityIds.Contains(command.ParentId))
                return;
            RaiseUpdate(command.ParentId);
            processedEntityIds.Add(command.ParentId);

        }

        public void Process(DeleteAttributeCommand command)
        {
        }

        public void Process(CreateReferenceCommand command)
        {
            RaiseCreateRelationship(new string[] { command.ParentType, command.ParentId, command.ChildType, command.ChildId, command.Role });
        }

        public void Process(DeleteReferenceCommand command)
        {
            RaiseRemoveRelationship(new string[] { command.ParentType, command.ParentId, command.ChildType, command.ChildId, command.Role });
        }

        #endregion

        public void ProcessCommands(Transaction transaction)
        {
            CommandCollection commandCollection = new CommandCollection();
            CommandCollection transactionCommands = transaction.PendingCommands;
            transaction.PendingCommands = commandCollection;
            foreach (Command c in transactionCommands)
            {
                cancelEventArgs = new CancelEntityEventArgs(false);
                c.Accept(this);
                if (!cancelEventArgs.Cancel && !cancelEventArgs.EntityChanged)
                    commandCollection.Add(c);
            }
        }
    }
}
